package com.cema.manage.config.Interceptor;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.cema.manage.common.exception.RiskException;
import com.cema.manage.common.utils.IpUtils;
import com.cema.manage.common.utils.encryption.RSAEncrypt;
import com.cema.manage.project.android.result.JsonResult;
import com.cema.manage.project.enums.RedisEnum;
import com.cema.manage.project.enums.UserStatusEnum;
import com.cema.manage.project.manage.antiCheat.service.IAntiCheatService;
import com.cema.manage.project.manage.antiCheatDetail.domain.AntiCheatDetail;
import com.cema.manage.project.manage.antiCheatDetail.service.IAntiCheatDetailService;
import com.cema.manage.project.manage.users.domain.Users;
import com.cema.manage.redis.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.UnknownHostException;


/**
 * @author Administrator
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(TokenInterceptor.class);
    private RedisService redisService;

    private IAntiCheatDetailService iAntiCheatDetailService;

    private IAntiCheatService iAntiCheatService;

    /**
     * 无需token验证用户
     */
    public TokenInterceptor() {

    }

    public TokenInterceptor(RedisService redisService, IAntiCheatDetailService iAntiCheatDetailService, IAntiCheatService iAntiCheatService) {
        this.redisService = redisService;
        this.iAntiCheatDetailService = iAntiCheatDetailService;
        this.iAntiCheatService = iAntiCheatService;
    }

//    /**
//     * 预处理回调方法，实现处理器的预处理
//     * 返回值：true表示继续流程；false表示流程中断，不会继续调用其他的拦截器或处理器
//     */
//    @Override
//    @ResponseBody
//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
//            throws Exception {
//        if (request.getMethod().equals("OPTIONS")) {
//            return true;
//        }
//        System.out.println("开始拦截........." + request.getRequestURI());
//        response.setCharacterEncoding("UTF-8");
//        response.setContentType("application/json; charset=utf-8");
//        ///////////////////////////////////获取签名/////////////////////////////////
//        String sign = request.getHeader("sign");
//        String timestampStr = request.getHeader("timestamp");
//        ///////////////////////////////////end/////////////////////////////////
//        if (sign != null && timestampStr != null) {
//            //解析签名:时间戳+tbb52sm 双重MD5加密
//            //int timestamp = (int) (System.currentTimeMillis() / 60000);
//
//            String sign2 = DigestUtils.md5Hex(timestampStr + RSAEncrypt.publicKey);
//            sign2 = DigestUtils.md5Hex(sign2);
//            //校验签名是否正确？
//            if (!sign.equals(sign2)) {
//                //throw new Exception("非法操作");
//                returnResponse(response, JsonResult.returnAuth());
//                return false;
//            }
//            String token = request.getParameter("token");
//            token = RSAEncrypt.decrypt(token);
//            System.out.println("token........." + token);
//            System.out.println("访问IP地址........." + IpUtils.getIpAddr(request));
//            //释放后台接口权限
//            if (StringUtils.isEmpty(token) && StringUtils.isEmpty(phone)) {
//                request.setAttribute("token", token);
//                return true;
//            }
//            Users users = (Users) redisService.get(token);
//            if (users != null) {
//                request.setAttribute("token", token);
//                return true;
//            } else {
//                returnResponse(response, JsonResult.returnAuth());
//                return false;
//            }
//
//        } else {
//            returnResponse(response, JsonResult.returnAuth());
//            return false;
//        }
//    }

    /**
     * 预处理回调方法，实现处理器的预处理
     * 返回值：true表示继续流程；false表示流程中断，不会继续调用其他的拦截器或处理器
     */
    @Override
    @ResponseBody
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (request.getMethod().equals("OPTIONS")) {
            return true;
        }
        log.info("开始拦截........." + request.getRequestURI());
        String token = request.getParameter("token");
        token = RSAEncrypt.decrypt(token);
        log.info("token........." + token);
        log.info("访问IP地址........." + IpUtils.getIpAddr(request));
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        Users users = (Users) redisService.get(token);
        if (ObjectUtil.isNull(users)) {
            returnResponse(response, JsonResult.returnResetLogin("登录失效、请重新登录"));
            return false;
        }
        try {
            iAntiCheatService.checkIp(users.getId(), IpUtils.getIpAddr(request));
        } catch (UnknownHostException e) {
            returnResponse(response, JsonResult.returnResetLogin("登录失效、请重新登录"));
            return false;
        } catch (RiskException e) {
            returnResponse(response, JsonResult.returnAuth(e.getMessage()));
            return false;
        }
        if (UserStatusEnum.USER_STATUS_VIOLATION.getValue().equals(users.getStatus())) {
            EntityWrapper<AntiCheatDetail> entityWrapper = new EntityWrapper<>();
            AntiCheatDetail entity = new AntiCheatDetail();
            entity.setUsId(users.getId());
            entityWrapper.setEntity(entity);
            AntiCheatDetail antiCheatDetail = iAntiCheatDetailService.selectOne(entityWrapper);
            returnResponse(response, JsonResult.returnAuth("系统判定用户ID：" + users.getId() + "存在违规嫌疑【" + antiCheatDetail.getAcdDesc() + "】如有疑问请微信扫码进群联系管理员："));
            return false;
        }
        request.setAttribute("token", token);
        return true;
    }

    private void returnResponse(HttpServletResponse response, JsonResult res) {
        PrintWriter printWriter = null;
        try {
            printWriter = response.getWriter();
            printWriter.write("{\"code\":" + res.getCode() + ",\"msg\":\"" + res.getMsg() + "\"}");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ObjectUtil.isNotNull(printWriter)) {
                printWriter.close();
            }
        }
    }

    /**
     * 后处理回调方法，实现处理器（controller）的后处理，但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub

    }

    /**
     * 整个请求处理完毕回调方法，即在视图渲染完毕时回调，
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间，
     * 还可以进行一些资源清理，类似于try-catch-finally中的finally，
     * 但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
            ex)
            throws Exception {
        // TODO Auto-generated method stub

    }

}
